﻿using Gobang.ToolClass;
using Gobang.ToolClass.Model;
using Gobang.ToolClass.Networking;
using Gobang.ToolClass.Networking.UDP;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Net;

namespace Gobang.Client.Common
{
    internal class NetworkingCenter
    {
        public static Lazy<IClientNetworking> ClientLazy { get; private set; }
        public static IClientNetworking Client => ClientLazy.Value;
        // 注册回调
        public static Action<MsgMergeModel, IPEndPoint> RegisteredAction;
        // 登录回调
        public static Action<MsgMergeModel, IPEndPoint> LoginAction;
        private static Thread _thread;
        static NetworkingCenter()
        {
            ClientLazy = new Lazy<IClientNetworking>(() =>
            {
                var client = new UDPClientTool("127.0.0.1", 10009);
                client.Active = true;
                return client;
            });

            Client.DataArrival = DataArrival;
            _thread = new Thread(Execute);
            _thread.Start();
        }
        private static IPEndPoint _remoteServerEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8090);
        public static IPEndPoint RemoteServerEP => _remoteServerEP;
        public static void SendToServer(byte[] data)
        {
            Send(data, RemoteServerEP);
        }
        public static void Send(byte[] data, IPEndPoint iPEndPoint)
        {
            Client.Send(iPEndPoint, data);
        }
        public static void Dispose()
        {
            _disposed = true;
            Client.Active = false;
        }
        private static ConcurrentQueue<ReceiveData> _receiveDatas = new ConcurrentQueue<ReceiveData>();
        private static void DataArrival(byte[] data, IPEndPoint iPEndPoint)
        {
            _receiveDatas.Enqueue(new ReceiveData
            {
                Data = data,
                IPPoint = iPEndPoint
            });
        }
        private static volatile bool _disposed = false;
        private static void Execute()
        {
            while (!_disposed)
            {
                if (!_receiveDatas.TryDequeue(out var result))
                {
                    Thread.Sleep(1);
                    continue;
                }
                try
                {
                    var mes = System.Text.Encoding.UTF8.GetString(result.Data);
                    MsgMergeModel msgMergeModel = mes.DeserializeObject<MsgMergeModel>();
                    switch (msgMergeModel.SendMsgType)
                    {
                        case MsgType.Msg:
                            Task.Factory.StartNew(() =>
                            {

                            });
                            break;
                        case MsgType.None:
                            Task.Factory.StartNew(() =>
                            {

                            });

                            break;
                        case MsgType.Command:

                            Task.Factory.StartNew(() =>
                            {
                                MsgTypeCommand(msgMergeModel, result.IPPoint);
                            });

                            break;
                    }
                }
                catch (Exception ex)
                {
#if DEBUG
                    Trace.WriteLine(ex.Message);
#endif
                }
            }
        }
        private static void MsgTypeCommand(MsgMergeModel msgMerge, IPEndPoint iPEndPoint)
        {
            switch (msgMerge.SendMsgCommand)
            {
                case MsgCommand.Registered:
                    RegisteredAction?.Invoke(msgMerge, iPEndPoint);
                    break;
                case MsgCommand.RegisterAt:
                    RegisteredAction?.Invoke(msgMerge, iPEndPoint);
                    break;
                case MsgCommand.Loginend:
                    LoginAction?.Invoke(msgMerge, iPEndPoint);
                    break;
            }
        }
    }
    public class ReceiveData
    {
        public byte[] Data { get; set; }
        public IPEndPoint IPPoint { get; set; }
    }
}
